package cn.signalpha.modules.shop.service;

import cn.hutool.core.date.DateUtil;
import cn.signalpha.common.annotation.OptimisticLockRetryAnnotation;
import cn.signalpha.common.enums.StatusEnum;
import cn.signalpha.common.exception.OptimisticLockRetryException;
import cn.signalpha.common.utils.Arith;
import cn.signalpha.core.log.exception.ServiceException;
import cn.signalpha.core.tool.support.Kv;
import cn.signalpha.core.tool.utils.*;
import cn.signalpha.modules.auth.dto.UserInfo;
import cn.signalpha.modules.com.dto.WalletDTO;
import cn.signalpha.modules.com.entity.enums.WalletAmountTypeEnum;
import cn.signalpha.modules.com.entity.enums.WalletTypeEnum;
import cn.signalpha.modules.shop.entity.GoodsComment;
import cn.signalpha.modules.shop.entity.Seller;
import cn.signalpha.modules.shop.entity.SellerRole;
import cn.signalpha.modules.shop.entity.SellerWallet;
import cn.signalpha.modules.shop.entity.enums.SellerAccountTypeEnum;
import cn.signalpha.modules.shop.mapper.SellerMapper;
import cn.signalpha.modules.shop.vo.SellerVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static cn.signalpha.common.cache.CacheNames.EXPIRATION_TIME_7;
import static cn.signalpha.common.cache.CacheNames.SELLER;

/**
 * 服务类
 *
 * @author signalpha
 */
@Slf4j
@Service
@AllArgsConstructor
public class SellerService extends ServiceImpl<SellerMapper, Seller> {

	private final SellerRoleService sellerRoleService;
	private final GoodsCommentService goodsCommentService;
	private final SellerWalletService sellerWalletService;

	/**
	 * 自定义分页
	 */
    public IPage<SellerVO> selectSellerPage(IPage<SellerVO> page, Map<String, Object> params) {
        return page.setRecords(baseMapper.selectSellerPage(page, params));
    }

	/**
	 * 自定义Wrapper
	 */
	public QueryWrapper<Seller> selectSellerWrapper(Map<String, Object> params) {
		QueryWrapper<Seller> wrapper = Wrappers.query();
		wrapper.lambda().in(ObjectUtil.isNotEmpty(params.get("ids")), Seller::getId, Func.toLongList(String.valueOf(params.get("ids"))));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("userId")), Seller::getUserId, params.get("userId"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("sellerId")), Seller::getSellerId, params.get("sellerId"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("status")), Seller::getStatus, params.get("status"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("accountType")), Seller::getAccountType, params.get("accountType"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("categoryId")), Seller::getCategoryId, params.get("categoryId"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("province")), Seller::getProvince, params.get("province"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("city")), Seller::getCity, params.get("city"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("district")), Seller::getDistrict, params.get("district"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("account")), Seller::getAccount, params.get("account"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("isPush")), Seller::getIsPush, params.get("isPush"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("isSelf")), Seller::getIsSelf, params.get("isSelf"));
		wrapper.lambda().like(ObjectUtil.isNotEmpty(params.get("name")), Seller::getName, params.get("name"));
		wrapper.lambda().like(ObjectUtil.isNotEmpty(params.get("mobile")), Seller::getMobile, params.get("mobile"));
		wrapper.lambda().like(ObjectUtil.isNotEmpty(params.get("keyword")), Seller::getKeyword, params.get("keyword"));
		wrapper.lambda().isNotNull(ObjectUtil.isNotEmpty(params.get("updateInfo")), Seller::getUpdateInfo);
		wrapper.lambda().ge(ObjectUtil.isNotEmpty(params.get("createTimeBegin")), Seller::getCreateTime, params.get("createTimeBegin"));
		wrapper.lambda().le(ObjectUtil.isNotEmpty(params.get("createTimeEnd")), Seller::getCreateTime, params.get("createTimeEnd"));
		wrapper.lambda().orderByDesc(Seller::getId);
		return wrapper;
	}

	/**
	 * 数量统计
	 */
	public long countByParams(Map<String, Object> params) {
		return count(selectSellerWrapper(params));
	}

	/**
	 * 数量统计
	 */
	public long countByAccount(String account) {
		return countByParams(Kv.create().set("account", account));
	}

	/**
	 * 获取基础信息
	 */
	@Cacheable(cacheNames = SELLER + EXPIRATION_TIME_7, key = "#id", unless="#result==null")
	public Seller getBaseById(Long id) {
		return baseMapper.selectById(id);
	}
	@CacheEvict(cacheNames = SELLER, key = "#id")
	public void removeCacheById(Long id) {
	}

	/**
	 * 获取商户评分
	 */
	public int score(Long sellerId) {
		List<GoodsComment> list = goodsCommentService.list(Wrappers.<GoodsComment>lambdaQuery()
			.select(GoodsComment::getGoodsScore).eq(GoodsComment::getSellerId, sellerId)
			.eq(GoodsComment::getIsShow, 1)
		);
		if(CollectionUtil.isEmpty(list)){
			return 5;
		}
		int score = (int) Math.round(Arith.div(list.stream().mapToInt(GoodsComment::getGoodsScore).sum(), list.size()));
		return score == 0 ? 5 : score;
	}

	/**
	 * 创建商户
	 */
	@Transactional(rollbackFor = Exception.class)
	public void createSeller(Seller seller) {
		if(countByAccount(seller.getAccount()) > 0){
			throw new ServiceException("商户账号已存在：" + seller.getAccount());
		}

		if(ObjectUtil.isEmpty(seller.getUserId())){
			seller.setUserId(0L);
		}
		if(StringUtil.isBlank(seller.getPassword())){
			seller.setPassword(seller.getMobile().substring(seller.getMobile().length() - 6));
		}

		seller.setId(null);
		seller.setStatus(StatusEnum.ON.getType());
		seller.setAccountType(SellerAccountTypeEnum.MAIN.getType());
		seller.setPassword(DigestUtil.encrypt(seller.getPassword()));
		seller.setExt(StringPool.EMPTY_JSON);
		seller.setIsOpenPick(0);
		seller.setPickConfig(StringPool.LEFT_SQ_BRACKET + StringPool.RIGHT_SQ_BRACKET);
		seller.setCreateTime(new Date());
		seller.setUpdateTime(seller.getCreateTime());
		baseMapper.insert(seller);

		//生成默认角色
		SellerRole sellerRole = new SellerRole();
		sellerRole.setSellerId(seller.getId());
		sellerRole.setParentId(0L);
		sellerRole.setRoleName("超级管理员");
		sellerRole.setRoleAlias("administrator");
		sellerRole.setSort(1);
		sellerRoleService.save(sellerRole);
		baseMapper.updateById(Seller.builder().id(seller.getId()).sellerId(seller.getId()).roleId(sellerRole.getId().toString()).build());
	}

	/**
	 * 更新用户余额
	 */
	@OptimisticLockRetryAnnotation
	public boolean updateSellerMoney(WalletDTO walletDTO) {
		Seller seller = getById(walletDTO.getUserId());
		if(ObjectUtil.isEmpty(seller)) {return false;}

		Double money = seller.getMoney();
		if(walletDTO.getType().equals(WalletTypeEnum.ADD.getType())){
			money = Arith.add(money, walletDTO.getAmount());
		}else if(walletDTO.getType().equals(WalletTypeEnum.SUB.getType())){
			money = Arith.sub(money, walletDTO.getAmount());
			if(money < 0){
				throw new ServiceException("余额不足");
			}
		}else{
			throw new ServiceException("计算类型不正确");
		}

		Date dateTime = DateUtil.date();
		if(updateById(Seller.builder().id(seller.getId()).money(money).updateTime(dateTime).version(seller.getVersion()).build())){
			SellerWallet userWallet = Objects.requireNonNull(BeanUtil.copy(walletDTO, SellerWallet.class));
			userWallet.setSellerId(walletDTO.getUserId());
			userWallet.setAmountType(WalletAmountTypeEnum.MONEY.getType());
			userWallet.setAmountLast(money);
			userWallet.setCreateTime(dateTime);
			sellerWalletService.save(userWallet);
		}else{
			log.error("id:[{}]更新商户余额失败", seller.getId());
			throw new OptimisticLockRetryException();
		}

		return true;
	}


	/**
	 * 用户信息
	 */
	public UserInfo userInfo(Long id) {
		return buildUserInfo(baseMapper.selectById(id));
	}

	/**
	 * 用户信息
	 */
	public UserInfo userInfo(String username, String password) {
		return buildUserInfo(baseMapper.selectOne(Wrappers.<Seller>lambdaQuery().eq(Seller::getAccount, username).eq(Seller::getPassword, password)));
	}

	/**
	 * 构建用户信息
	 */
	private UserInfo buildUserInfo(Seller seller) {
		if (ObjectUtil.isEmpty(seller)) {
			return null;
		}
		if(seller.getStatus().equals(StatusEnum.OFF.getType())){
			throw new ServiceException("商户已被冻结，请联系系统管理员");
		}

		UserInfo userInfo = Objects.requireNonNull(BeanUtil.copy(seller, UserInfo.class));
		userInfo.setNickName(seller.getName());
		userInfo.setAccount(seller.getMobile());
		userInfo.setTenantId(seller.getSellerId().toString());
		userInfo.setRoles(sellerRoleService.getRoleAliases(seller.getRoleId()));
		return userInfo;
	}


}
